package com.leenmvc.core.security.service.core;

import com.leenmvc.core.annotation.TransactionMulti;
import com.leenmvc.core.base.BaseService;
import com.leenmvc.core.dao.communal.Wrapper;
import com.leenmvc.core.exception.BusinessException;
import com.leenmvc.core.security.entity.core.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysRoleService extends BaseService<SysRole> {

    private final static Logger logger = LoggerFactory.getLogger(SysRoleService.class);

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Autowired
    private SysUserService sysUserService;

    @Override
    @TransactionMulti
    public <T> boolean insert(T t) {
        SysRole role = (SysRole)t;
        String pids = findPids(role, new StringBuilder());
        role.setPids(pids);
        boolean insert = super.insert(t);
        // 新增菜单与角色关系
        List<SysRoleMenu> roleMenuList = role.getRoleMenuList();
        if (roleMenuList.size() > 0){
            roleMenuList.forEach(sysRoleMenu -> {
                sysRoleMenu.setRoleId(role.getId());
                sysRoleMenuService.insert(sysRoleMenu);
            });
        }
        return insert;
    }

    /**
     * 把部门的所有上级部门的Id用,拼接成字符串pids
     *
     * @param role
     * @return
     */
    public String findPids(SysRole role, StringBuilder pids) {
        if (null == pids) {
            pids = new StringBuilder();
        }
        if (null == role) {
            return null;
        }
        SysRole parent = null;
        //如果上级Id不等于空
        Long pid = role.getPid();
        if (pid == 0) {
            //自己就是顶级Id
            role.setTopId(0L);
            pids.append(pid);
            return pids.toString();
        } else {
            //拿到父实体
            parent = findParent(role);
            //如果父实体的父Id不为空
            if (null != parent && 0 == parent.getPid() && null == parent.getPids()) {
                role.setTopId(parent.getId());
                pids.append(parent.getId());
                return pids.toString();
            } else {
                pids.append(parent.getId() + ",");
                return findPids(parent, pids);
            }
        }
    }

    /**
     * 拿到自己父级
     *
     * @param role
     * @return
     */
    public SysRole findParent(SysRole role) {
        List<SysRole> list = listBySqlKey("getById", "id", role.getPid());
        if (0 == list.size()) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 修改角色
     * @param t  角色实体
     * @param <T>
     * @return
     */
    @Override
    @TransactionMulti
    public <T> boolean update(T t) {
        SysRole role  = (SysRole)t;
        // 先删除之前绑定的菜单与角色关系
        sysRoleMenuService.delete("roleId",role.getId());

        // 在新增修改后的菜单与角色关系
        List<SysRoleMenu> roleMenuList = role.getRoleMenuList();
        if (roleMenuList.size() > 0){
            roleMenuList.forEach(sysRoleMenu -> {
                sysRoleMenuService.insert(sysRoleMenu);
            });
        }
        // 如果修改了子角色已绑定的菜单，需要删除子角色对应菜单关系
        List<String> delMenuIdList = role.getDelMenuIdList();
        if (delMenuIdList.size() > 0) {
            // 获取改角色所有子角色
            List<SysRole> roleList = query(getQueryWrapper().like("pids", role.getId()));
            if(roleList.size() > 0 ){
                // 删除子角色对应菜单关系
                roleList.forEach(role1 -> {
                    delMenuIdList.forEach(menuId->{
                        sysRoleMenuService.delete("roleId",role1.getId(),"menuId",Long.parseLong(menuId));
                    });
                });
            }
        }
        return super.update(t);
    }

    /**
     * 新增用户按钮，回显页面数据
     */
    public List roleAddUserList(Long roleId){
        // 获取默认角色用户
        List<SysUser> users1 = sysUserService.getList("roleId", 717041517844426752L);
        // 添加标识
        if (users1.size() > 0){
            users1.forEach(sysUser -> {
                sysUser.setSign(0);
            });
        }
        // 获取改角色已绑定用户
        List<SysUser> users2 = sysUserService.getList("roleId", roleId);
        if (users2.size() > 0){
            users2.forEach(sysUser -> {
                sysUser.setSign(1);
            });
        }
        users1.addAll(users2);
        return users1;
    }

    /**
     * 修改角色与用户关系
     */
    @TransactionMulti
    public void updateRoleUser(Long roleId, List<String> userList){
        //先将所有已绑定的用户解绑
        List<SysUser> sysUsers = sysUserService.getList("roleId", roleId);
        if (sysUsers.size() > 0){
            sysUsers.forEach(sysUser -> {
                sysUser.setRoleId(717041517844426752L);
                sysUserService.update(sysUser);
            });
        }

        // 在将修改后的关系绑定
        if (userList.size() > 0){
            userList.forEach(userId ->{
                // 获取到用户
                SysUser user = sysUserService.get(Long.parseLong(userId));
                user.setRoleId(roleId);
                sysUserService.update(user);
            });
        }
    }

    /**
     * 重写删除方法
     * 删除关联表中的记录，然后删除主表记录
     *
     * @param ids
     * @return
     */
    @TransactionMulti
    public int deleteByIds(Object[] ids) {
        for(Object id: ids) {
            // 如果需要删除的角色下有子角色，则无法删除
            List<SysRole> roleList = getList("pid", id);
            if (roleList.size() > 0){
                throw new BusinessException("删除角色失败,请先删除子角色");
            }

            // 删除角色关联菜单数据
            Wrapper deleteWrapper = getDeleteWrapper(SysRoleMenu.class);
            deleteWrapper.eq("roleId", id);
            logger.info("成功删除了关联的角色菜单数据， 共删除了 【{}】 条数据！" + delByWrapper(deleteWrapper));

            // 解绑关联该角色的用户，使用户变为默认用户
            List<SysUser> userList = sysUserService.getList("roleId", id);
            if (userList.size() > 0 ){
                userList.forEach(sysUser -> {
                    sysUser.setRoleId(717041517844426752L);
                    sysUserService.update(sysUser);
                });
            }
        }
        return super.deleteByIds(ids);
    }

}
